package com.mutual.webchat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.URL;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.UUID;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.utils.HttpsUtils;
import com.mutual.app.pojo.AppResult;
import com.mutual.appUserInfo.pojo.AppUserInfoProduct;
import com.mutual.appUserInfo.service.AppUserInfoProductService;
import com.mutual.commom.controller.BaseController;
import com.mutual.commom.pojo.ReturnResult;
import com.mutual.commom.service.RedisService;
import com.mutual.commom.util.DateUtil;
import com.mutual.commom.util.JSONUtil;
import com.mutual.commom.wechat.ConstantUtil;
import com.mutual.commom.wechat.MD5Util;
import com.mutual.commom.wechat.PayCommonUtil;
import com.mutual.commom.wechat.WXUtil;
import com.mutual.commom.wechat.XMLUtil;
import com.mutual.commom.zfb.AlipayConfig;
import com.mutual.index.controller.IndexController;

@Controller
@RequestMapping("/wechat")
public class TenPayController extends BaseController{

	private static final Logger log = LoggerFactory.getLogger(TenPayController.class);
	
	@Resource
	private AppUserInfoProductService appUserInfoProductService;
	
	@Resource
	private RedisService redisService;
	
	/**
	 * 下单
	 * @return
	 * @throws IOException 
	 * @throws JDOMException 
	 */
	@RequestMapping("/order")
	@ResponseBody
	public AppResult order(HttpServletRequest request) throws JDOMException, IOException {
		AppResult appResult = new AppResult();
		String APPID = ConstantUtil.APP_ID;
        String MERID = ConstantUtil.MCH_ID;
        String SIGNKEY = ConstantUtil.APP_KEY;
		String spbill_create_ip = PayCommonUtil.getRemortIP(request);//生产
		System.out.println("spbill_create_ip="+spbill_create_ip);
		String scene_info = "{\"h5_info\": {\"type\":\"Wap\",\"wap_url\": \"http://wq.guanaichou.cn\",\"wap_name\": \"ggg\"}}";//我这里是网页入口，app入口参考文档的安卓和ios写法
		String tradeType = "MWEB";//H5支付标记
		String MD5 = "MD5";//虽然官方文档不是必须参数，但是不送有时候会验签失败
		JSONObject result = new JSONObject();
		String body = ConstantUtil.BODY;
		String total_amount = "1";//前端上送的支付金额
		String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
		//金额转化为分为单位 微信支付以分为单位
//		String finalmoney = StringUtils.getMoney(total_amount);
		int randomNum  = (int) (Math.random() * 1999+5000);
		String out_trade_no = DateTime.now().toString("yyyyMMddHHmmssSSS");
//		String out_trade_no = "201906032153135926624";
		//随机数 
//		String nonce_str= PayCommonUtil.createNoncestr();
		String nonce_str="ff5wd8BoEOPhAn1W";
		StringBuilder sb = new StringBuilder();
		sb.append("appid="+APPID);
		sb.append("&body="+body);
		sb.append("&mch_id="+MERID);
		sb.append("&nonce_str="+nonce_str);
		sb.append("&notify_url="+(super.getBasePath()+"wechat/orderBack"));
		sb.append("&out_trade_no="+out_trade_no);
		sb.append("&scene_info="+scene_info);
		sb.append("&spbill_create_ip="+this.getIpAddr(request));
		sb.append("&total_fee="+total_amount);
		sb.append("&trade_type="+tradeType);
	    sb.append("&key="+SIGNKEY);
	    System.out.println("sb="+sb);
	    String sign = MD5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase();
	    System.out.println("sign="+sign);
	    log.info("签名数据:"+sign);
	    String xml="<xml>"+
	            "<appid>"+ APPID+"</appid>"+
	            "<body>"+body+"</body>"+
	            "<mch_id>"+ MERID+"</mch_id>"+
	            "<nonce_str>"+nonce_str+"</nonce_str>"+
	            "<notify_url>"+(super.getBasePath()+"wechat/orderBack")+"</notify_url>"+
	            "<out_trade_no>"+out_trade_no+"</out_trade_no>"+
	            "<scene_info>"+scene_info+"</scene_info>"+
	            "<spbill_create_ip>"+this.getIpAddr(request)+"</spbill_create_ip>"+
	            "<total_fee>"+total_amount+"</total_fee>"+//
	            "<trade_type>"+tradeType+"</trade_type>"+
	            "<sign>"+sign+"</sign>"+
	            "</xml>";
	    
	    System.out.println(xml);
		
	    String resultObj = PayCommonUtil.sendPost("https://api.mch.weixin.qq.com/pay/unifiedorder"
                ,xml);
        
        log.info("信息返回："+resultObj);
        
        Map map = XMLUtil.doXMLParse(resultObj);
        
        if("SUCCESS".equals((String)map.get("return_code"))){
        	String url = (String)map.get("mweb_url");
    	    appResult.setData(url);
        }else {
        	appResult.setStatus(AppResult.STATUS_FAILED);
        }
		return appResult;
	}
	/**
	 *
	 * @return
	 * var param = "?appUserId="+appUser.id+"&idCode="+idCode+"&type="+vue.selectType;
				param+="&productId="+vue.productId+"&applyPeopleId="+vue.applyPeopleId;
	 */
	@RequestMapping("/getAuthorizeURL")
	@ResponseBody
	public AppResult forwardWechat(AppUserInfoProduct appUserInfoProduct) {
		AppResult appResult = new AppResult();
		StringBuilder su = new StringBuilder();
		su.append("https://open.weixin.qq.com/connect/oauth2/authorize?appid=");
		su.append(ConstantUtil.APP_ID);
		su.append("&redirect_uri=");
		String redirectUri = "http://wq.guanaichou.cn/APP/yiyuan_buy.html";
		su.append(URLEncoder.encode(redirectUri));
		su.append("&response_type=code&scope=snsapi_userinfo&state=STATE&connect_redirect=1#wechat_redirect");
		appResult.setData(su.toString());
		log.info(JSONObject.toJSONString(appResult));
		redisService.saveRedisValueTime(ConstantUtil.APP_ID+appUserInfoProduct.getAppUserId(), JSONObject.toJSONString(appUserInfoProduct), 5*60);
		return appResult;
	}
	
	
	
	@RequestMapping("/getChooseProduct")
	@ResponseBody
	public AppResult getChooseProduct(int appUserId) {
		AppResult appResult = new AppResult();
		String redisResult = redisService.getValueByRedisKey(ConstantUtil.APP_ID+appUserId);
		appResult.setData(JSONObject.parseObject(redisResult,AppUserInfoProduct.class));
		log.info("产品信息选择查看返回：{}", JSONUtil.getJSONFromObj(appResult));
		return appResult;
	}
	
	
	
	
	
	@RequestMapping("/jsAPIorder")
	@ResponseBody
	public AppResult jsAPIorder(HttpServletRequest request,AppUserInfoProduct appUserInfoProduct) throws JDOMException, IOException {
		AppResult appResult = new AppResult();
		String out_trade_no = DateTime.now().toString("yyyyMMddHHmmssSSS");
		appUserInfoProduct.setOrderNum(out_trade_no);
		appUserInfoProduct.setPayType(AppUserInfoProduct.PAY_TYPE_WECHAT);
		appResult = this.dealLoalData(appUserInfoProduct, appResult);
		if(!AppResult.STATUS_SUCCESS.equals(appResult.getStatus())) {
			return appResult;
		}
		String APPID = ConstantUtil.APP_ID;
        String MERID = ConstantUtil.MCH_ID;
        String SIGNKEY = ConstantUtil.APP_KEY;
		String code = request.getParameter("code");
		log.info("app:"+request.getParameter("app"));
		log.info("Code:"+code);
		String jsonOpenString = PayCommonUtil.sendGet("https://api.weixin.qq.com/sns/oauth2/access_token?appid="+APPID+"&secret="+ConstantUtil.APP_SECRET+"&code="+code+"&grant_type=authorization_code", null);
		log.info("jsonOpenString:"+jsonOpenString);
		JSONObject openIdJson = JSONObject.parseObject(jsonOpenString);
		String openId = openIdJson.getString("openid");
		String tradeType = "JSAPI";//JSAPI支付标记
		String MD5 = "MD5";//虽然官方文档不是必须参数，但是不送有时候会验签失败
		String body = ConstantUtil.BODY;
		String total_amount = (String)appResult.getData();//前端上送的支付金额
		//随机数 
		String nonce_str= PayCommonUtil.createNoncestr();
		StringBuilder sb = new StringBuilder();
		sb.append("appid="+APPID);
		sb.append("&body="+body);
		sb.append("&mch_id="+MERID);
		sb.append("&nonce_str="+nonce_str);
		sb.append("&notify_url="+(super.getBasePath()+"wechat/orderBack?out_trade_no="+out_trade_no));
		sb.append("&openid="+openId);
		sb.append("&out_trade_no="+out_trade_no);
		sb.append("&spbill_create_ip="+this.getIpAddr(request));
		sb.append("&total_fee="+total_amount);
		sb.append("&trade_type="+tradeType);
	    sb.append("&key="+SIGNKEY);
	    System.out.println("sb="+sb);
	    String sign = MD5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase();
	    System.out.println("sign="+sign);
	    log.info("签名数据:"+sign);
	    String xml="<xml>"+
	            "<appid>"+ APPID+"</appid>"+
	            "<body>"+body+"</body>"+
	            "<mch_id>"+ MERID+"</mch_id>"+
	            "<nonce_str>"+nonce_str+"</nonce_str>"+
	            "<notify_url>"+(super.getBasePath()+"wechat/orderBack?out_trade_no="+out_trade_no)+"</notify_url>"+
	            "<openid>"+openId+"</openid>"+
	            "<out_trade_no>"+out_trade_no+"</out_trade_no>"+
	            "<spbill_create_ip>"+this.getIpAddr(request)+"</spbill_create_ip>"+
	            "<total_fee>"+total_amount+"</total_fee>"+//
	            "<trade_type>"+tradeType+"</trade_type>"+
	            "<sign>"+sign+"</sign>"+
	            "</xml>";
	    
	    log.info(xml);
		
	    String resultObj = PayCommonUtil.sendPost("https://api.mch.weixin.qq.com/pay/unifiedorder"
                ,xml);
        
        log.info("信息返回："+resultObj);
        
        Map map = XMLUtil.doXMLParse(resultObj);
        
        if("SUCCESS".equals((String)map.get("return_code"))){
        	SortedMap<String, String> jsonObject = new TreeMap<String,String>();
        	jsonObject.put("appId", APPID);
        	jsonObject.put("timeStamp", out_trade_no);
        	jsonObject.put("nonceStr", nonce_str);
        	jsonObject.put("package", "prepay_id="+(String)map.get("prepay_id"));
        	jsonObject.put("signType", MD5);
        	String paySign = PayCommonUtil.createSign("UTF-8", jsonObject);
        	jsonObject.put("paySign", paySign);
    	    appResult.setData(jsonObject);
        }else {
        	appResult.setStatus(AppResult.STATUS_FAILED);
        }
		return appResult;
	}
	
	/**
	 * 本地数据处理
	 * @param appUserInfoProduct
	 * @param appResult
	 * @return
	 */
	public AppResult dealLoalData(AppUserInfoProduct appUserInfoProduct,AppResult appResult) {
		ReturnResult result=appUserInfoProductService.buyProduct(appUserInfoProduct);
		log.info("buyProductPayZfb 内部保存返回数据：{}",JSONUtil.getJSONFromObj(result));
		if(result.getStatus()!=ReturnResult.STATUS_SUCCESS){
			log.info(result.getReturnMsg().toString());
			appResult.setMsg(result.getReturnMsg().toString());
			appResult.setStatus(AppResult.STATUS_FAILED);
			return appResult;
		}
		AppUserInfoProduct selectData=(AppUserInfoProduct)result.getData();
		selectData.setAmount(selectData.getAmount().multiply(BigDecimal.valueOf(100)));
		String WIDtotal_amount = String.valueOf(selectData.getAmount().intValue());
		appResult.setData(WIDtotal_amount);
		return appResult;
	}
	
	public String getIpAddr(HttpServletRequest request){  
        String ipAddress = request.getHeader("x-forwarded-for");  
            if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {  
                ipAddress = request.getHeader("Proxy-Client-IP");  
            }  
            if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {  
                ipAddress = request.getHeader("WL-Proxy-Client-IP");  
            }  
            if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {  
                ipAddress = request.getRemoteAddr();  
                if(ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")){  
                    //根据网卡取本机配置的IP  
                    InetAddress inet=null;  
                    try {  
                        inet = InetAddress.getLocalHost();  
                    } catch (UnknownHostException e) {  
                        e.printStackTrace();  
                    }  
                    ipAddress= inet.getHostAddress();  
                }  
            }  
            //对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割  
            if(ipAddress!=null && ipAddress.length()>15){ //"***.***.***.***".length() = 15  
                if(ipAddress.indexOf(",")>0){  
                    ipAddress = ipAddress.substring(0,ipAddress.indexOf(","));  
                }  
            }  
            return ipAddress;   
	  }

	/**
	 * 下单回调
	 * @return
	 * @throws JDOMException 
	 * @throws IOException 
	 */
	@ResponseBody
	@RequestMapping("/orderBack")
	public AppResult orderBack(@RequestParam Map<String,String> param,HttpServletRequest request,HttpServletResponse response,AppUserInfoProduct appUserInfoProduct) throws JDOMException{
		BufferedReader bufferedReader=null;
		try {
			AppResult appResult =new AppResult();
			InputStreamReader reader = new InputStreamReader(request.getInputStream());
			bufferedReader = new  BufferedReader(reader);
			String line = null;
			StringBuilder su=new StringBuilder();
			while((line=bufferedReader.readLine())!=null) {
				su.append(line);
			}
			log.info("回调信息返回：{}",su.toString());
			if(StringUtils.isEmpty(su.toString())) {
				appResult.setMsg("回调为空");
				appResult.setStatus(AppResult.STATUS_FAILED);
				return appResult;
			}
			Map map = XMLUtil.doXMLParse(su.toString());
//			Map map = new HashMap();
//			map.put("return_code", "SUCCESS");
//			map.put("out_trade_no", "20190624182257420");
	        if("SUCCESS".equals((String)map.get("return_code"))){
	        	String out_trade_no = map.get("out_trade_no").toString();
				appUserInfoProduct.setOrderNum(out_trade_no);
				appUserInfoProduct.setStatus(AppUserInfoProduct.STATUS_BUY_SUCCESS);
				appUserInfoProduct.setApplyDate(new Date());
				log.info("支付成功：{}",out_trade_no);
				appResult.setStatus(AppResult.STATUS_SUCCESS);
				appResult.setMsg("支付成功");
	        }else {
	        	String out_trade_no = map.get("out_trade_no").toString();
	        	appUserInfoProduct.setOrderNum(out_trade_no);
				appUserInfoProduct.setStatus(AppUserInfoProduct.STATUS_BUY_FAILED);
				appUserInfoProduct.setApplyDate(new Date());
				log.info("支付失败：{}",out_trade_no);
				appResult.setStatus(AppResult.STATUS_SUCCESS);
				appResult.setMsg("支付失败");
	        }
	        appUserInfoProductService.updateBuyProductStatus(appUserInfoProduct);
	        return appResult;
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			if(bufferedReader!=null) {
				try {
					bufferedReader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return new AppResult(AppResult.STATUS_FAILED);
	}
	
	public static void main(String[] args) {
//		String out_trade_no = DateTime.now().toString("yyyyMMddHHmmssSSS");
//		System.out.println(out_trade_no.length());
//		
//		String url = "<mweb_url><![CDATA[https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx2016121516420242444321ca0631331346&package=1405458241]]></mweb_url>";
//		
//		System.out.println(url.substring(url.indexOf("<mweb_url><![CDATA["), url.indexOf("]]></mweb_url>")));
		
		System.out.println(URLEncoder.encode("http://wq.guanaichou.cn/APP/forwardWechat.html?app=1"));
		
		AppResult appResult = new AppResult();
		StringBuilder su = new StringBuilder();
		su.append("https://open.weixin.qq.com/connect/oauth2/authorize?appid=");
		su.append(ConstantUtil.APP_ID);
		su.append("&redirect_uri=");
		String redirectUri = "http://wq.guanaichou.cn/APP/yiyuan_buy.html";
		su.append(URLEncoder.encode(redirectUri));
		su.append("&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect");
		appResult.setData(su.toString());
		log.info(JSONObject.toJSONString(appResult));
	}
}